home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_13_01 / kuzdrall / longtxf.c < prev    next >
C/C++ Source or Header  |  1994-12-06  |  4KB  |  116 lines

  1. /* ***< LNGTXF.CEE   >*** */
  2. /* Copyright 1994 James A. Kuzdrall
  3.    Free license to this software is granted only if the above
  4.    copyright credit is included in the source code */
  5.  
  6.   /* put system headers here */
  7. #include  <stdio.h>    /* usual definitions */
  8.  
  9.   /* use limit if does not exceed range of host machine */
  10. #define MAXLNG  2147483647L  /* limit +2147483647 */
  11. #define MINLNG -2147483648L  /* limit -2147483648 */
  12. #define XFER_ERROR -1        /* a non-zero integer */
  13.  
  14. /***< fputl     >*** ++++++++++++++++++++++++++++++++++++++++++++++ *
  15.  
  16.   USE....... Convert host's long integer to the 4-byte, 2's comple-
  17.     ment, MSB-first standard transfer format.  Send the four bytes
  18.     to the output stream fp.
  19.   RETURNS... Non-zero if error; otherwise, 0
  20.     No number sent if error.
  21.   ERRORS.... Disk errors of putc().
  22.     Overrange if exceeds transfer range, 2147483647 to -2147483648.
  23. */
  24.  
  25. int  fputl(lp,fp)
  26.   long  *lp;       /* long to put on disk */
  27.   FILE  *fp;       /* file pointer given by fopen() */
  28.   {
  29.   int   ix;        /* byte counter */
  30.   long  absl;      /* absolute value of *lp */
  31.   unsigned int  byt[5];   /* byt[0] is most significant */
  32.   int   err;
  33.  
  34.   if( MINLNG != -2147483647  &&  *lp == MINLNG ) {
  35.     byt[0]= 0x80;   /* set 2's complement -2147483648 */
  36.     byt[1]= byt[2]= byt[3]= 0;
  37.     }
  38.   else {
  39.     /* avoid problem with -MINLNG in 2's comp, 4-byte */
  40.     absl= (*lp <= -1L  &&  *lp >= -2147483647) ? -*lp : *lp;
  41.  
  42.     /* divide magnitude into bytes; if neg, negate in 2's comp */
  43.     byt[4]= 0x100;                   /* becomes 1 after >> 8 */
  44.     for( ix= 3; ix >= 0; ix-- ) {    /* process from LSB to MSB */
  45.       byt[ix]= (absl >> (8*(3-ix))) & 0xff;
  46.       if( *lp <= -1L )
  47.         byt[ix]= (byt[ix] ^ 0xff) + (byt[ix+1] >> 8);
  48.       }
  49.     }
  50.  
  51.   err= XFER_ERROR;                 /* preset */
  52.   /* if in range, send MSB first */
  53.   if( *lp <= MAXLNG  &&  (*lp >= -2147483647  ||  *lp == MINLNG) ) {
  54.     for( ix= 0; ix < 4; ix++ )
  55.       if( putc(byt[ix],fp) == EOF )
  56.         goto plxit;
  57.     err= 0;
  58.     }
  59.   plxit:
  60.   return( err );
  61.   }
  62.  
  63.  
  64. /***< fgetl     >*** ++++++++++++++++++++++++++++++++++++++++++++++ *
  65.  
  66.   USE....... Read a standard format, 4-byte long integer from the
  67.     input stream fp and convert it to the host's long format.
  68.   RETURNS...  ERROR if error; otherwise, 0
  69.     Places answer at pointer if no errors.
  70.   ERRORS.... From getc() only; generates no errors of its own.
  71. */
  72.  
  73. int  fgetl(lp,fp)
  74.   long  *lp;       /* place where answer goes */
  75.   FILE  *fp;       /* file pointer given by fopen() */
  76.   {
  77.   int   ix;        /* byte counter */
  78.   char  neg;       /* non-zero (true) if original nr was negative */
  79.   long  ans;       /* temporary */
  80.   unsigned int  byt[5];   /* byt[0] is most significant */
  81.   int   err;
  82.  
  83.   err= XFER_ERROR;                 /* preset */
  84.   for( ix= 0; ix<4; ix++ ) {       /* byte read from MSB to LSB */
  85.     if( (byt[ix]= getc(fp)) == EOF )
  86.       goto glxit;
  87.     byt[ix] &= 0xff;               /* remove any high bits */
  88.     }
  89.  
  90.   /* detect special case, -2147483648 in non-2's complement host */
  91.   if( MINLNG == -2147483647  &&  byt[0] == 0x80  &&  !byt[1]  &&
  92.       !byt[2]  &&  !byt[3] )
  93.     goto glxit;     /* out-of-range error */
  94.   err= 0;                          /* no error */ 
  95.  
  96.   ans= 0L;
  97.   byt[4]= 0x100;                   /* becomes 1 after >> 8 */
  98.   neg= byt[0] & 0x80;
  99.   for( ix= 3; ix >= 0; ix-- ) {
  100.     if( neg )  /* make negative nrs positive by 2's comp negate */
  101.       byt[ix]= (byt[ix] ^ 0xff) + (byt[ix+1] >> 8);
  102.     ans |= ((long )(byt[ix] & 0xff)) << 8*(3-ix);
  103.     }
  104.  
  105.   /* handle MINLNG separately; has negate and range problems */
  106.   if( byt[0] & 0x80 )              /* only MINLNG is still neg */
  107.     *lp= MINLNG;
  108.   else                             /* for all but MINLNG */
  109.     *lp= neg ? -ans : ans;         /* let host install sign */
  110.  
  111.   glxit:
  112.   return( err );
  113.   }
  114.  
  115.  
  116.